home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / dev / c / vbcc.lha / vbcc / pasm / instructions.c < prev    next >
C/C++ Source or Header  |  1998-02-17  |  42KB  |  1,252 lines

  1. /* $VER: pasm instructions.c V0.8 (14.02.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.8 (14.02.98) phx
  16.  *      Alignment list for each section. This fixes the problems
  17.  *      with optimizations.
  18.  * V0.7 (02.01.98) phx
  19.  *      Implemented optimization OPT_FAR_BRANCH.
  20.  * v0.6 (30.10.97) phx
  21.  *      No more warnings for val@l(rA), where val is > 0x7fff.
  22.  *      Warnings for optional, 64-bit and supervisor instructions
  23.  *      can be suppressed.
  24.  * v0.5 (03.10.97) phx
  25.  *      Auto-converting (rA) into 0(rA) had lead to conflicts with terms.
  26.  *      For example: (x+y)(rA)
  27.  * v0.4 (05.07.97) phx
  28.  *      AA bit in BC instructions is set to allow correct EHF reloction
  29.  *      (by using AmigaDOS HUNK_RELRELOC16. This should be no problem,
  30.  *      because absolute branches are not supported by EHF anyway.
  31.  *      Branch prediction with BCA didn't work correctly.
  32.  *      Relative branches into other sections are allowed, but the
  33.  *      user will be warned, because not all object formats / linkers
  34.  *      support it.
  35.  *      Omitting zero in load/store instructions is allowed, e.g.
  36.  *      "rD,(rA)" will be converted into "rD,0(rA)".
  37.  *      R_PPC_TOC16 support for T_DD- and T_DS-type instructions.
  38.  * v0.3 (05.04.97) phx
  39.  *      An external symbol@l/h/ha, used in d(Rn) addressing mode, got
  40.  *      R_PPC_ADDR16 relocation instead R_PPC_ADDR16_LO/HI/HA.
  41.  *      Little-endian support.
  42.  * v0.2 (25.03.97) phx
  43.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  44.  *      or ELF output format may be selected. ELF is default for all
  45.  *      currently supported platforms. PPCasm supports nine different
  46.  *      relocation types (there are much more...).
  47.  *      Compiles and works also under NetBSD/amiga (68k).
  48.  *      Changed function declaration to 'new style' in all sources
  49.  *      (to avoid problems with '...' for example).
  50.  *      @l/h/ha is allowed for all displacements.
  51.  * v0.1 (11.03.97) phx
  52.  *      First test version with all PowerPC instructions and most
  53.  *      important directives. Only raw, absolute output.
  54.  *      Although all 32- and 64-bit PowerPC instructions are imple-
  55.  *      mented, too few are really tested till now. I'm expecting many
  56.  *      bugs in this long list.
  57.  *      'la' is the only extended mnemonic, which was implemented as a
  58.  *      real instruction and not by a macro. It is possible to imple-
  59.  *      ment all extended mnemonics here, but it would be much work.
  60.  *      Maybe later, to improve speed. ;)
  61.  * v0.0 (21.02.97) phx
  62.  *      File created.
  63.  */
  64.  
  65.  
  66. #define INSTRUCTIONS_C
  67. #include "ppcasm.h"
  68.  
  69.  
  70. void instr(struct GlobalVars *,struct ParsedLine *);
  71. char *check_comma(char *);
  72. void pcadd(struct GlobalVars *,unsigned long);
  73. void store_byte(struct GlobalVars *,uint8);
  74. void store_half(struct GlobalVars *,uint16);
  75. void store_word(struct GlobalVars *,uint32);
  76. void store_float(struct GlobalVars *,double);
  77. void store_double(struct GlobalVars *,double);
  78. void store_space(struct GlobalVars *,unsigned long);
  79.  
  80. static void opt_far_branch(struct GlobalVars *,struct ParsedLine *,
  81.                            uint32 *,uint32 *,int32 *,char *);
  82. static void swapops(uint32 *,uint32 *);
  83. static int count_operands(struct GlobalVars *,char *);
  84. static bool chk_regindir(char *);
  85. static void move_symbols(struct GlobalVars *,uint32,int32);
  86. static void move_aligned_symbols_offset(struct GlobalVars *,
  87.                                         struct AlignPoint *,uint32,int32);
  88. static void move_aligned_symbols_all(struct GlobalVars *gv,
  89.                                      struct AlignPoint *ap,int32);
  90.  
  91.  
  92.  
  93. struct CPUInstr instructions[] = {
  94.   /* standard PowerPC instruction set */
  95.   { 0,"add",0,T_X,31,0,0,(0<<10)+(266<<1)+0 },
  96.   { 0,"add.",0,T_X,31,0,0,(0<<10)+(266<<1)+1 },
  97.   { 0,"addo",0,T_X,31,0,0,(1<<10)+(266<<1)+0 },
  98.   { 0,"addo.",0,T_X,31,0,0,(1<<10)+(266<<1)+1 },
  99.   { 0,"addc",0,T_X,31,0,0,(0<<10)+(10<<1)+0 },
  100.   { 0,"addc.",0,T_X,31,0,0,(0<<10)+(10<<1)+1 },
  101.   { 0,"addco",0,T_X,31,0,0,(1<<10)+(10<<1)+0 },
  102.   { 0,"addco.",0,T_X,31,0,0,(1<<10)+(10<<1)+1 },
  103.   { 0,"adde",0,T_X,31,0,0,(0<<10)+(138<<1)+0 },
  104.   { 0,"adde.",0,T_X,31,0,0,(0<<10)+(138<<1)+1 },
  105.   { 0,"addeo",0,T_X,31,0,0,(1<<10)+(138<<1)+0 },
  106.   { 0,"addeo.",0,T_X,31,0,0,(1<<10)+(138<<1)+1 },
  107.   { 0,"addi",F_SIGNED,T_DI,14,0,0,0 },
  108.   { 0,"addic",F_SIGNED,T_DI,12,0,0,0 },
  109.   { 0,"addic.",F_SIGNED,T_DI,13,0,0,0 },
  110.   { 0,"addis",F_SIGNED,T_DI,15,0,0,0 },
  111.   { 0,"addme",F_SUPP_B,T_X,31,0,0,(0<<10)+(234<<1)+0 },
  112.   { 0,"addme.",F_SUPP_B,T_X,31,0,0,(0<<10)+(234<<1)+1 },
  113.   { 0,"addmeo",F_SUPP_B,T_X,31,0,0,(1<<10)+(234<<1)+0 },
  114.   { 0,"addmeo.",F_SUPP_B,T_X,31,0,0,(1<<10)+(234<<1)+1 },
  115.   { 0,"addze",F_SUPP_B,T_X,31,0,0,(0<<10)+(202<<1)+0 },
  116.   { 0,"addze.",F_SUPP_B,T_X,31,0,0,(0<<10)+(202<<1)+1 },
  117.   { 0,"addzeo",F_SUPP_B,T_X,31,0,0,(1<<10)+(202<<1)+0 },
  118.   { 0,"addzeo.",F_SUPP_B,T_X,31,0,0,(1<<10)+(202<<1)+1 },
  119.   { 0,"and",F_SWAP,T_X,31,0,0,(28<<1)+0 },
  120.   { 0,"and.",F_SWAP,T_X,31,0,0,(28<<1)+1 },
  121.   { 0,"andc",F_SWAP,T_X,31,0,0,(60<<1)+0 },
  122.   { 0,"andc.",F_SWAP,T_X,31,0,0,(60<<1)+1 },
  123.   { 0,"andi.",F_SWAP,T_DI,28,0,0,0 },
  124.   { 0,"andis.",F_SWAP,T_DI,29,0,0,0 },
  125.   { 0,"b",F_SIGNED,T_I,18,0,0,0 },
  126.   { 0,"bl",F_SIGNED,T_I,18,0,0,1 },
  127.   { 0,"ba",0,T_I,18,0,0,2 },
  128.   { 0,"bla",0,T_I,18,0,0,3 },
  129.   { 0,"bc",F_SIGNED,T_B,16,0,0,0 },
  130.   { 0,"bcl",F_SIGNED,T_B,16,0,0,1 },
  131.   { 0,"bca",0,T_B,16,0,0,2 },
  132.   { 0,"bcla",0,T_B,16,0,0,3 },
  133.   { 0,"bcctr",0,T_XLB,19,0,0,(528<<1)+0 },
  134.   { 0,"bcctrl",0,T_XLB,19,0,0,(528<<1)+1 },
  135.   { 0,"bclr",0,T_XLB,19,0,0,(16<<1)+0 },
  136.   { 0,"bclrl",0,T_XLB,19,0,0,(16<<1)+1 },
  137.   { 0,"cmp",0,T_CMP,31,0,0,(0<<1) },
  138.   { 0,"cmpl",0,T_CMP,31,0,0,(32<<1) },
  139.   { 0,"cmpi",F_SIGNED|F_SUPP_B,T_CMP,11,0,0,0 },
  140.   { 0,"cmpli",F_SUPP_B,T_CMP,10,0,0,0 },
  141.   { 0,"cntlzd",F_SWAP|F_SUPP_B|F_64BIT,T_X,31,0,0,(58<<1)+0 },
  142.   { 0,"cntlzd.",F_SWAP|F_SUPP_B|F_64BIT,T_X,31,0,0,(58<<1)+1 },
  143.   { 0,"cntlzw",F_SWAP|F_SUPP_B,T_X,31,0,0,(26<<1)+0 },
  144.   { 0,"cntlzw.",F_SWAP|F_SUPP_B,T_X,31,0,0,(26<<1)+1 },
  145.   { 0,"crand",0,T_X,19,0,0,(257<<1) },
  146.   { 0,"crandc",0,T_X,19,0,0,(129<<1) },
  147.   { 0,"creqv",0,T_X,19,0,0,(289<<1) },
  148.   { 0,"crnand",0,T_X,19,0,0,(225<<1) },
  149.   { 0,"crnor",0,T_X,19,0,0,(33<<1) },
  150.   { 0,"cror",0,T_X,19,0,0,(449<<1) },
  151.   { 0,"crorc",0,T_X,19,0,0,(417<<1) },
  152.   { 0,"crxor",0,T_X,19,0,0,(193<<1) },
  153.   { 0,"dcbf",F_SUPP_D,T_X,31,0,0,(86<<1) },
  154.   { 0,"dcbi",F_SUPP_D|F_SUPER,T_X,31,0,0,(470<<1) },
  155.   { 0,"dcbst",F_SUPP_D,T_X,31,0,0,(54<<1) },
  156.   { 0,"dcbt",F_SUPP_D,T_X,31,0,0,(278<<1) },
  157.   { 0,"dcbtst",F_SUPP_D,T_X,31,0,0,(246<<1) },
  158.   { 0,"dcbz",F_SUPP_D,T_X,31,0,0,(1014<<1) },
  159.   { 0,"divd",F_64BIT,T_X,31,0,0,(0<<10)+(489<<1)+0 },
  160.   { 0,"divd.",F_64BIT,T_X,31,0,0,(0<<10)+(489<<1)+1 },
  161.   { 0,"divdo",F_64BIT,T_X,31,0,0,(1<<10)+(489<<1)+0 },
  162.   { 0,"divdo.",F_64BIT,T_X,31,0,0,(1<<10)+(489<<1)+1 },
  163.   { 0,"divdu",F_64BIT,T_X,31,0,0,(0<<10)+(457<<1)+0 },
  164.   { 0,"divdu.",F_64BIT,T_X,31,0,0,(0<<10)+(457<<1)+1 },
  165.   { 0,"divduo",F_64BIT,T_X,31,0,0,(1<<10)+(457<<1)+0 },
  166.   { 0,"divduo.",F_64BIT,T_X,31,0,0,(1<<10)+(457<<1)+1 },
  167.   { 0,"divw",0,T_X,31,0,0,(0<<10)+(491<<1)+0 },
  168.   { 0,"divw.",0,T_X,31,0,0,(0<<10)+(491<<1)+1 },
  169.   { 0,"divwo",0,T_X,31,0,0,(1<<10)+(491<<1)+0 },
  170.   { 0,"divwo.",0,T_X,31,0,0,(1<<10)+(491<<1)+1 },
  171.   { 0,"divwu",0,T_X,31,0,0,(0<<10)+(459<<1)+0 },
  172.   { 0,"divwu.",0,T_X,31,0,0,(0<<10)+(459<<1)+1 },
  173.   { 0,"divwuo",0,T_X,31,0,0,(1<<10)+(459<<1)+0 },
  174.   { 0,"divwuo.",0,T_X,31,0,0,(1<<10)+(459<<1)+1 },
  175.   { 0,"eciwx",0,T_X,31,0,0,(310<<1) },
  176.   { 0,"ecowx",0,T_X,31,0,0,(438<<1) },
  177.   { 0,"eieio",F_SUPP_D|F_SUPP_A|F_SUPP_B,T_X,31,0,0,(854<<1) },
  178.   { 0,"eqv",F_SWAP,T_X,31,0,0,(284<<1)+0 },
  179.   { 0,"eqv.",F_SWAP,T_X,31,0,0,(284<<1)+0 },
  180.   { 0,"extsb",F_SWAP|F_SUPP_B,T_X,31,0,0,(954<<1)+0 },
  181.   { 0,"extsb.",F_SWAP|F_SUPP_B,T_X,31,0,0,